package com.ls.utils.weixin;

import com.alibaba.fastjson.JSONObject;
import com.ls.utils.JsonUtils;
import com.ls.utils.http.HttpUtils;
import com.ls.utils.redis.RedisClient;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;

/**
 * 微信工具类
 * AccessToken 、Ticket 统一通过此类获取
 */
@Component
public class WxUtil {
    private static final Logger logger = LoggerFactory.getLogger(WxUtil.class);

    /**
     * redis工具类
     */
    @Autowired
    private RedisClient redisClient;

    /**
     * 获取AccessToken
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public String getAccessToken(String appId, String appSecret) {
        try {
            String key = "accessToken" + appId;
            String accessToken = redisClient.getJsonString(key);
            if (StringUtils.isBlank(accessToken)) {
                String responseStr = HttpUtils.sendSyncGet("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=APPSECRET".replace("APPID", appId).replace("APPSECRET", appSecret));
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                accessToken = jsonObject.getString("access_token");
                if (null != accessToken) {
                    redisClient.save(key, accessToken);
                    redisClient.setExpireTime(key, 7100);
                }
            }
            logger.info("accessToken:{}" + accessToken);
            return accessToken;
        } catch (Exception e) {
            logger.error("getAccessToken{}", e.getStackTrace().toString());
        }
        return "";
    }

    /**
     * 获取Ticket
     *
     * @param appId
     * @param appSecret
     * @return
     */
    public String getTicket(String appId, String appSecret) {
        try {
            String key = "ticket" + appId;
            String ticket = redisClient.getJsonString(key);
            if (StringUtils.isBlank(ticket)) {
                String token = getAccessToken(appId, appSecret);
                String responseStr = HttpUtils.sendSyncGet("https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token=ACCESS_TOKEN&type=jsapi".replace("ACCESS_TOKEN", token));
                JSONObject jsonObject = JSONObject.parseObject(responseStr);
                ticket = jsonObject.getString("ticket");
                if (null != ticket) {
                    redisClient.save(key, ticket);
                    redisClient.setExpireTime(key, 7100);
                }
            }
            logger.info("ticket:{}" + ticket);
            return ticket;
        } catch (Exception e) {
            logger.error("getTicket:{}", e.getStackTrace().toString());
        }
        return "";
    }

    /**
     * 获取Signature
     *
     * @param url
     * @param nonceStr
     * @param timeStamp
     * @param appId
     * @param appSecret
     * @return
     */
    public String getScanSignature(String url, String nonceStr, String timeStamp, String appId, String appSecret) {
        try {
            String ticket = getTicket(appId, appSecret);
            String mwStr = "jsapi_ticket=" + ticket + "&noncestr=" + nonceStr + "&timestamp=" + timeStamp + "&url=" + url;
            String retSignature = DigestUtils.sha1Hex(mwStr);
            return retSignature;
        } catch (Exception e) {
            logger.error("getScanSignature:{}", e.getStackTrace().toString());
        }
        return "";
    }


    /**
     * 根据前端传入的code获取用户openID和一个特殊的网页授权access_token
     * <p>
     * code说明 ： code作为换取access_token的票据，每次用户授权带上的code将不一样，code只能使用一次，5分钟未被使用自动过期。
     * <p>
     *
     * @param appId
     * @param appSecret
     * @param code
     * @return JSONObject中数据获取方式       String openId = jsonObject.getString("openid");
     * String accessToken = jsonObject.getString("access_token");
     * @throws IOException
     */
    public static JSONObject getOpenIdAndAccessToken(String appId, String appSecret, String code) throws Exception {
        logger.info("获取openId 参数 appid:[{}],appSecret:[{}],code:[{}]", appId, appSecret, code);
        String url = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code",
                appId, appSecret, code);
        String jsonString = HttpUtils.sendSyncGet(url);
        logger.info("获取openId 结果 jsonString：[{}]", jsonString);
        return JsonUtils.toJsonObject(jsonString);
    }

    /**
     * 获取用户信息请求
     *
     * @param openId      openID
     * @param accessToken 上面getOpenIdAndAccessToken方法返回的
     * @return
     * @throws IOException
     */
    public static JSONObject getUserInfo(String openId, String accessToken) throws Exception {
        String url = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN",
                accessToken, openId);
        String jsonString = HttpUtils.sendSyncGet(url);
        return JsonUtils.toJsonObject(jsonString);
    }

}
